/*
 * Linguagens de Programação - 2º Ano - 2º Semestre - Linguagem de Programação C
 * Autor: Duarte Peres / Nº5621
 *
 * timedemo.c - Os procedimentos apresentados são os mesmos do módulo teachers.c, com algumas
 *				alterações por exemplo substituição dos PyObject* para que o gprof funcionasse
 *				correctamente. Este módulo de C compila e chama o gprof para o calculo do tempo
 *				de execução de cada procedimento implementados. 
 *				Granularity: each sample hit covers 2 byte(s) for 20.00% of 0.05 seconds
 */


#include <stdio.h>
#include <stdlib.h>
#include <python2.6/Python.h>
#include <sqlite3.h>
#include <time.h>

int contagem;

static int callback(void *NotUsed, int argc, char **argv, char **azColName){
	contagem = atoi( argv[0] ? argv[0] : "NULL");
	return 0;
}

static int callbackList(PyObject* list, int argc, char **argv, char **azColName){
	PyList_Append(list, PyString_FromString(argv[0]));
	return 0;
}


static int PerYear(int year, char namefile[25]){
	FILE *file;
		file = fopen(namefile, "a");
    	fprintf(file, "O numero total de docentes no ano 200%d -> %d\n",year , contagem);
    	fclose(file);	
        return 0;
}

static int PerYearPerEstablishment(int year, char establ[50],char namefile[25]){
	FILE *file;
		file = fopen(namefile, "a");
    	fprintf(file, "O numero total de docentes no ano 200%d do estabelecimento %s -> %d\n",year, establ, contagem);
    	fclose(file);	
        return 0;
}

static int PerYearPerDegree(int year, char degree[50],char namefile[25]){
	FILE *file;
		file = fopen(namefile, "a");
    	fprintf(file, "O numero total de docentes no ano 200%d com grau %s -> %d\n",year, degree, contagem);
    	fclose(file);	
        return 0;
}


static int PerYearPerDegreePerEstablishment(int year, char degree[50], char establ[50],char namefile[25]){
	FILE *file;
		file = fopen(namefile, "a");
    	fprintf(file, "O numero total de docentes no ano 200%d com grau %s no estabelecimento %s -> %d\n",year, degree, establ,contagem);
    	fclose(file);	
        return 0;
}

static int ListEstablPerYear(int year,char namefile[25], PyObject* list){
	FILE *file;
	int i;
		file = fopen(namefile, "a");
		fprintf(file, "No ano 200%d:\n",year);
		for(i = 0; i < PyList_Size(list); i++)
		{
    		fprintf(file, "%s\n" , PyString_AsString(PyList_GetItem(list, i)));
        }
    	fclose(file);	
        return 0;
}

static int ListTitularesPerYearPerDegree(int year, char degree[50],char namefile[25], PyObject* list){
	FILE *file;
	int i;
		file = fopen(namefile, "a");
		fprintf(file, "No ano 200%d e grau %s:\n",year, degree);
		for(i = 0; i < PyList_Size(list); i++){
    		fprintf(file, "%s\n" , PyString_AsString(PyList_GetItem(list, i)));
        }
    	fclose(file);	
        return 0;
}

static int ListPersonnelLeave(int year, char establ[50],char namefile[25], PyObject* list){
	FILE *file;
	int i;
		file = fopen(namefile, "a");
		fprintf(file, "No ano 200%d no estabelecimento %s estas pessoas deixaram a instituição:\n",year, establ);
		for(i = 0; i < PyList_Size(list); i++){
    		fprintf(file, "%s\n" , PyString_AsString(PyList_GetItem(list, i)));
        }
    	fclose(file);	
        return 0;
}

static int ListPersonnelEntry(int year, char establ[50],char namefile[25], PyObject* list){
	FILE *file;
	int i;
		file = fopen(namefile, "a");
		fprintf(file, "\nNo ano 200%d no estabelecimento %s estas pessoas entraram na instituição:\n",year, establ);
		for(i = 0; i < PyList_Size(list); i++){
    		fprintf(file, "%s\n" , PyString_AsString(PyList_GetItem(list, i)));
        }
    	fclose(file);	
        return 0;
}


//############################ ESTATÍSTICAS ########################################

int queryPerYear(int year){;
	char* argv1 = "rebides.db";
	char* argv2 = (char *) malloc(sizeof (char[BUFSIZ]));
	
	char* Syear = (char *) malloc(sizeof (char));
	
	strcpy(argv2, "SELECT COUNT(DISTINCT docente) FROM fichas_docencia WHERE ano = ");
	sprintf(Syear, "%d", year);
	strcat(argv2, Syear);

	sqlite3 *db;
	char *zErrMsg = 0;
	int rc;
	rc = sqlite3_open(argv1, &db);

	rc = sqlite3_exec(db, argv2, callback, 0, &zErrMsg);
	
	if( rc!=SQLITE_OK ){
		fprintf(stderr, "SQL error: %s\n", zErrMsg);
		sqlite3_free(zErrMsg);
	}
	sqlite3_close(db);
	
	PerYear(year , "ContagemDocentesPorAno.txt");
	  
	free (argv2);
	free (Syear); 
	return contagem;

}



int queryPerEstablishmentPerYear(int year, char* establishment){
	char* argv1 = "rebides.db";
	char* argv2 = (char *) malloc(sizeof (char[200]));
	char* Syear = (char *) malloc(sizeof (char));
	
	strcpy(argv2, "SELECT COUNT(DISTINCT docente) FROM fichas_docencia WHERE ano = ");
	sprintf(Syear, "%d", year);
	strcat(argv2, Syear); 
	char* more= " AND estabelecimento = '";
	strcat(argv2, more);
	strcat(argv2, establishment);
	strcat(argv2,"'"); 
	
	sqlite3 *db;
	char *zErrMsg = 0;
	int rc;
	rc = sqlite3_open(argv1, &db);

	rc = sqlite3_exec(db, argv2, callback, 0, &zErrMsg);
	
	if( rc!=SQLITE_OK ){
		fprintf(stderr, "SQL error: %s\n", zErrMsg);
		sqlite3_free(zErrMsg);
	}
	sqlite3_close(db);
	
	PerYearPerEstablishment(year, establishment, "ContagemDocentesPorAnoPorEstabelecimento.txt");
	
	free (argv2);
	free (Syear);
	return contagem;
}



int queryPerDegreePerYear(int year, char* degree){
	char* argv1 = "rebides.db";
	
	char* argv2 = (char *) malloc(sizeof (char[200]));
	char* Syear = (char *) malloc(sizeof (char));
	

	strcpy(argv2, "SELECT COUNT(DISTINCT docente) FROM fichas_docencia WHERE ano = ");
	sprintf(Syear, "%d", year);
	strcat(argv2, Syear);
	char* more = " AND grau ='";
	strcat(argv2, more);
	strcat(argv2, degree);
	strcat(argv2,"'"); 
	
	sqlite3 *db;
	char *zErrMsg = 0;
	int rc;
	rc = sqlite3_open(argv1, &db);

	rc = sqlite3_exec(db, argv2, callback, 0, &zErrMsg);
	
	if( rc!=SQLITE_OK ){
		fprintf(stderr, "SQL error: %s\n", zErrMsg);
		sqlite3_free(zErrMsg);
	}
	sqlite3_close(db);
	
	PerYearPerDegree(year, degree,"ContagemDocentesPorAnoPorGrau.txt");
	free (argv2);
	free (Syear);
	return contagem;
}


int queryPerEstablishmentPerDegreePerYear(int year, char* degree, char* establishment){
	
	char* argv1 = "rebides.db";
	char* argv2 = (char *) malloc(sizeof (char[200]));
	char* Syear = (char *) malloc(sizeof (char));
	
	strcpy(argv2, "SELECT COUNT(DISTINCT docente) FROM fichas_docencia WHERE ano = ");
	sprintf(Syear, "%d", year);
	strcat(argv2, Syear);
	char* more = " AND grau ='";
	strcat(argv2, more);
	strcat(argv2, degree);
	strcat(argv2,"'"); 
	more = " AND estabelecimento='";
	strcat(argv2, more);
	strcat(argv2, establishment);
	strcat(argv2,"'");
	
	sqlite3 *db;
	char *zErrMsg = 0;
	int rc;
	rc = sqlite3_open(argv1, &db);

	rc = sqlite3_exec(db, argv2, callback, 0, &zErrMsg);
	
	if( rc!=SQLITE_OK ){
		fprintf(stderr, "SQL error: %s\n", zErrMsg);
		sqlite3_free(zErrMsg);
	}
	sqlite3_close(db);
	
	PerYearPerDegreePerEstablishment(year, degree, establishment, "ContagemDocentesPorAnoPorGrauPorEstab.txt");
	
	free (argv2);
	free (Syear);

	return contagem;
}


//######################### LISTAS #######################################


PyObject* queryListEstablishmentPerYear(int year){
    
    PyObject* list = PyList_New(0);
    
	char* argv1 = "rebides.db";
	char* argv2 = (char *) malloc(sizeof (char[200]));
	char* Syear = (char *) malloc(sizeof (char));
	
	strcpy(argv2, "SELECT DISTINCT estabelecimento FROM fichas_docencia WHERE ano = ");
	sprintf(Syear, "%d", year);
	strcat(argv2, Syear); 
	sqlite3 *db;
	char *zErrMsg = 0;
	int rc;
	rc = sqlite3_open(argv1, &db);
	rc = sqlite3_exec(db, argv2, callbackList, list, &zErrMsg);
	
	if( rc!=SQLITE_OK ){
		fprintf(stderr, "SQL error: %s\n", zErrMsg);
		sqlite3_free(zErrMsg);
	}
	sqlite3_close(db);
	
	free (argv2);
	free (Syear);
	
	ListEstablPerYear(year,"ListaEstabelecimentosPorAno.txt",list);
	return  list;
}


PyObject* queryListHoldersPerDegreePerYear(int year, char* degree){
	
	PyObject* list = PyList_New(0);
	char* argv1 = "rebides.db";

	char* argv2 = (char *) malloc(sizeof (char[200]));
	char* Syear = (char *) malloc(sizeof (char));
	
	strcpy(argv2, "SELECT DISTINCT docente FROM fichas_docencia WHERE ano = ");
	sprintf(Syear, "%d", year);
	strcat(argv2, Syear);  
	char* more = " AND grau ='";
	strcat(argv2, more);
	strcat(argv2, degree);
	strcat(argv2,"'"); 

	sqlite3 *db;
	char *zErrMsg = 0;
	int rc;
	rc = sqlite3_open(argv1, &db);

	rc = sqlite3_exec(db, argv2, callbackList, list, &zErrMsg);
	
	if( rc!=SQLITE_OK ){
		fprintf(stderr, "SQL error: %s\n", zErrMsg);
		sqlite3_free(zErrMsg);
	}
	sqlite3_close(db);
	free (argv2);
	free (Syear);
	
	ListTitularesPerYearPerDegree(year, degree, "ListaTitularesPorAnoPorGrau.txt", list);
	return list;
}

int queryNumDocentes(int year, char* establishment){
	char* argv1 = "rebides.db";
	char* argv2 = (char *) malloc(sizeof (char[200]));
	char* Syear = (char *) malloc(sizeof (char));
	
	strcpy(argv2, "SELECT COUNT(DISTINCT docente) FROM fichas_docencia WHERE ano = ");
	sprintf(Syear, "%d", year);
	strcat(argv2, Syear); 
	char* more= " AND estabelecimento = '";
	strcat(argv2, more);
	strcat(argv2, establishment);
	strcat(argv2,"'"); 
	
	sqlite3 *db;
	char *zErrMsg = 0;
	int rc;
	rc = sqlite3_open(argv1, &db);

	rc = sqlite3_exec(db, argv2, callback, 0, &zErrMsg);
	
	if( rc!=SQLITE_OK ){
		fprintf(stderr, "SQL error: %s\n", zErrMsg);
		sqlite3_free(zErrMsg);
	}
	sqlite3_close(db);
	
	free (argv2);
	free (Syear);
	return contagem;
}


int queryListLeavingOREntry(int year, char* establishment){
	
	PyObject* list = PyList_New(0);
	
	char* argv1 = "rebides.db";

	char* argv2 = (char *) malloc(sizeof (char[200]));
	char* Syear = (char *) malloc(sizeof (char));
	
	strcpy(argv2, "SELECT DISTINCT docente FROM fichas_docencia WHERE ano = ");
	sprintf(Syear, "%d", year);
	strcat(argv2, Syear);  
	char* more = " AND estabelecimento ='";
	strcat(argv2, more);
	strcat(argv2, establishment);
	strcat(argv2,"'"); 

	sqlite3 *db;
	char *zErrMsg = 0;
	int rc;
	rc = sqlite3_open(argv1, &db);

	rc = sqlite3_exec(db, argv2, callbackList, list, &zErrMsg);
	
	if( rc!=SQLITE_OK ){
		fprintf(stderr, "SQL error: %s\n", zErrMsg);
		sqlite3_free(zErrMsg);
	}
	sqlite3_close(db);
	
	int total1 = queryNumDocentes(year, establishment);
	int total2 = queryNumDocentes(year+1, establishment);
	
	int diference = total1 - total2;
	
	if(diference < 0)
	{
		ListPersonnelLeave(year, establishment,"ListadeAbandonos.txt", list);
	}
	else if(diference > 0){   
		ListPersonnelEntry(year, establishment,"ListadeEntradas.txt", list);
	}else
	
	free (argv2);
	free (Syear);
	return contagem;
}



/* Este método, será chamado pelo gprof para calcular o tempo de execução de todos os métodos.
 * A partir do ciclo 'for' dentro do método posso executar todos os métodos percorrendo todos os anos e para os métodos
 * que necessitam de outros parâmetros foram previamente definidos, simulando assim o funcionamento
 * do módulo principal quando executado.
 */

int main()
{
	int i;
	int a;
	int b;
	int e;
	int h;
	PyObject* k;
	PyObject* l;
	PyObject* m;	
	
	for(i=0;i<10;i++)
	{
	
		a = queryPerYear(i);
		b = queryPerEstablishmentPerYear(i,"Academia Militar");
		e = queryPerDegreePerYear(i,"Licenciatura");
		h = queryPerEstablishmentPerDegreePerYear(i,"Mestrado","Instituto Politécnico de Beja - Escola Superior de Tecnologia e Gestão de Beja");
		k = queryListEstablishmentPerYear(i);
		l = queryListHoldersPerDegreePerYear(i, "Licenciatura");
		m = queryListLeavingOREntry(i, "Instituto Politécnico de Beja - Escola Superior de Tecnologia e Gestão de Beja");
	}
	return 0;
}